/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.client;

import com.google.gwt.core.client.JavaScriptObject;

/**
 * Part loading request, sent to OPPartsLoader to ask for loading a specific part.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 08 January 2010
 */
public final class OPPartLoadingRequest extends JavaScriptObject {

    /**
     * Returns a part loading request for the given service name.
     * 
     * @param service
     *            the name of the part service to load. Shouldn't be null.
     * @param callback
     *            the callback to call when the part is loaded and binded. Can be null.
     * @return the request for loading this service. Cannot be null.
     */
    public static final OPPartLoadingRequest partLoadingRequestFactory(final String service, final OPPartLoadedCallback callback) {
        assert service != null : "parameter service shouldn't be null";

        OPPartLoadedCallbackCaller callbackCaller = null;
        if (callback != null) {
            callbackCaller = new OPPartLoadedCallbackCaller(callback);
        }

        return partLoadingRequestFactoryImpl(service, callbackCaller);
    }

    /**
     * Real implementation of returning a part loading request for the given service name.
     * 
     * @param service
     *            the name of the part service to load.
     * @param callback
     *            the callback to call when the part is loaded and binded.
     * @return
     */
    private static final native OPPartLoadingRequest partLoadingRequestFactoryImpl(final String service, final OPPartLoadedCallbackCaller callback) /*-{
        var request = {};
        request.service = service;
        request.wasExecutedSynchronously = false;
        if (callback != null) {
            request.callbackSuccess = function() {
                return $entry(callback.@fr.openparts.OpenParts.client.OPPartLoadedCallbackCaller::onSuccess()());
            };
            request.callbackTimeout = function() {
                return $entry(callback.@fr.openparts.OpenParts.client.OPPartLoadedCallbackCaller::onTimeout()());
            };
        } else {
            request.callbackSuccess = null;
            request.callbackTimeout = null;
        }
        return request;
    }-*/;

    /**
     * Protected constructor, necessary because it's a JavaScriptObject.
     */
    protected OPPartLoadingRequest() {
    }

    /**
     * Returns the service name.
     * 
     * @return the service name.
     */
    public final native String getService() /*-{
        return this.service;
    }-*/;
    
    /**
     * Set the request as having being executed synchronously: the service was in fact already loaded.
     * Do not call directly, it is called by {@link OPPartsLoader} when the request is executed.
     */
    public final native void setAsHavingBeenExecutedSynchronously() /*-{
        this.wasExecutedSynchronously = true;
    }-*/;
    
    /**
     * Returns true if this request was executed synchronously, false otherwise.
     * This method should be called after the command has been send to be executed, not before. It will always returns false before the request is executed.
     *
     * @return true if this request was executed synchronously, false otherwise.
     */
    public final native boolean wasExecutedSynchronously() /*-{
        return this.wasExecutedSynchronously;
    }-*/;

    /**
     * Call the onSuccess callback. Don't do anything if there is no such callback.
     */
    public final native void onSuccess() /*-{
        if (this.callbackSuccess != null) {
            this.callbackSuccess();
        }
    }-*/;

    /**
     * Call the onTimeout callback. Don't do anything if there is no such callback.
     */
    public final native void onTimeout() /*-{
        if (this.callbackTimeout != null) {
            this.callbackTimeout();
        }
    }-*/;

}
